home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / ufw / applications.py next >
Text File  |  2009-08-26  |  6KB  |  210 lines

  1. #
  2. # applications.py: common classes for ufw
  3. #
  4. # Copyright 2008-2009 Canonical Ltd.
  5. #
  6. #    This program is free software: you can redistribute it and/or modify
  7. #    it under the terms of the GNU General Public License version 3,
  8. #    as published by the Free Software Foundation.
  9. #
  10. #    This program is distributed in the hope that it will be useful,
  11. #    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. #    GNU General Public License for more details.
  14. #
  15. #    You should have received a copy of the GNU General Public License
  16. #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. #
  18.  
  19. from ConfigParser import *
  20. import os
  21. import re
  22. from stat import *
  23. import ufw.util
  24. from ufw.util import debug, warn
  25. from ufw.common import UFWError
  26.  
  27. def get_profiles(dir):
  28.     '''Get profiles found in profiles database.  Returns dictionary with
  29.        profile name as key and tuples for fields
  30.     '''
  31.     if not os.path.isdir(dir):
  32.         err_msg = _("Profiles directory does not exist") % (dir)
  33.         raise UFWError("Error: profiles directory does not exist")
  34.  
  35.     max_size = 10 * 1024 * 1024  # 10MB
  36.     profiles = {}
  37.  
  38.     files = os.listdir(dir)
  39.     files.sort()
  40.  
  41.     total_size = 0
  42.     pat = re.compile(r'^\.')
  43.     for f in files:
  44.         abs = dir + "/" + f
  45.         if not os.path.isfile(abs):
  46.             continue
  47.  
  48.         if pat.search(f):
  49.             debug("Skipping '%s': hidden file" % (f))
  50.             continue
  51.  
  52.         if f.endswith('.dpkg-new') or f.endswith('.dpkg-old') or \
  53.            f.endswith('.dpkg-dist') or f.endswith('.rpmnew') or \
  54.            f.endswith('.rpmsave') or f.endswith('~'):
  55.             debug("Skipping '%s'" % (f))
  56.             continue
  57.  
  58.     # Try to gracefully handle huge files for the user (no security
  59.         # benefit, just usability)
  60.         size = 0
  61.         try:
  62.             size = os.stat(abs)[ST_SIZE]
  63.         except Exception:
  64.             warn_msg = _("Skipping '%s': couldn't stat") % (f)
  65.             warn(warn_msg)
  66.             continue
  67.  
  68.         if size > max_size:
  69.             warn_msg = _("Skipping '%s': too big") % (f)
  70.             warn(warn_msg)
  71.             continue
  72.  
  73.         if total_size + size > max_size:
  74.             warn_msg = _("Skipping '%s': too many files read already") % (f)
  75.             warn(warn_msg)
  76.             continue
  77.  
  78.         total_size += size
  79.  
  80.         cdict = RawConfigParser()
  81.         try:
  82.             cdict.read(abs)
  83.         except Exception:
  84.             warn_msg = _("Skipping '%s': couldn't process") % (f)
  85.             warn(warn_msg)
  86.             continue
  87.  
  88.         # If multiple occurences of profile name, use the last one
  89.         for p in cdict.sections():
  90.             if len(p) > 64:
  91.                 warn_msg = _("Skipping '%s': name too long") % (p)
  92.                 warn(warn_msg)
  93.                 continue
  94.  
  95.             if not valid_profile_name(p):
  96.                 warn_msg = _("Skipping '%s': invalid name") % (p)
  97.                 warn(warn_msg)
  98.                 continue
  99.  
  100.             try:
  101.                 ufw.util.get_services_proto(p)
  102.                 warn_msg = _("Skipping '%s': also in /etc/services") % (p)
  103.                 warn(warn_msg)
  104.                 continue
  105.             except Exception:
  106.                 pass
  107.  
  108.             skip = False
  109.             for key, value in cdict.items(p):
  110.                 if len(key) > 64:
  111.                     warn_msg = _("Skipping '%s': field too long") % (p)
  112.                     warn(warn_msg)
  113.                     skip = True
  114.                     break
  115.                 if len(value) > 1024:
  116.                     warn_msg = _("Skipping '%(value)s': value too long for " \
  117.                                  "'%(field)s'") % \
  118.                                  ({'value': p, 'field': key})
  119.                     warn(warn_msg)
  120.                     skip = True
  121.                     break
  122.             if skip:
  123.                 continue
  124.  
  125.             if profiles.has_key(p):
  126.                 warn_msg = _("Duplicate profile '%s', using last found") % (p)
  127.                 warn(warn_msg)
  128.  
  129.             pdict = {}
  130.             for key, value in cdict.items(p):
  131.                 #debug("add '%s' = '%s' to '%s'" % (key, value, p))
  132.                 pdict[key] = value
  133.  
  134.             profiles[p] = pdict
  135.  
  136.     return profiles
  137.  
  138. def valid_profile_name(name):
  139.     '''Only accept a limited set of characters for name'''
  140.     # Reserved profile name
  141.     if name == "all":
  142.         return False
  143.  
  144.     # Require first character be alpha, so we can avoid collisions with port
  145.     # numbers.
  146.     if re.match(r'^[a-zA-Z][a-zA-Z0-9 _\-\.+]*$', name):
  147.         return True
  148.     return False
  149.  
  150. def verify_profile(name, profile):
  151.     '''Make sure profile has everything needed'''
  152.     app_fields = ['title', 'description', 'ports']
  153.  
  154.     for f in app_fields:
  155.         if not profile.has_key(f):
  156.             err_msg = _("Profile '%(fn)s' missing required field '%(f)s'") % \
  157.                         ({'fn': name, 'f': f})
  158.  
  159.             raise UFWError(err_msg)
  160.         elif not profile[f]:
  161.             err_msg = _("Profile '%(fn)s' has empty required field '%(f)s'") \
  162.                         % ({'fn': name, 'f': f})
  163.             raise UFWError(err_msg)
  164.  
  165.     ports = profile['ports'].split('|')
  166.     if len(ports) < 1:
  167.         err_msg = _("No ports found in profile '%s'") % (name)
  168.         return False
  169.  
  170.     try:
  171.         for p in ports:
  172.             (port, proto) = ufw.util.parse_port_proto(p)
  173.             # quick check if error in profile
  174.             #if not proto:
  175.             #    proto = "any"
  176.             rule = ufw.common.UFWRule("ACCEPT", proto, port)
  177.             debug(rule)
  178.     except Exception, e:
  179.         debug(e)
  180.         err_msg = _("Invalid ports in profile '%s'") % (name)
  181.         raise UFWError(err_msg)
  182.  
  183.     return True
  184.  
  185. def get_title(profile):
  186.     '''Retrieve the title from the profile'''
  187.     str = ""
  188.     field = 'title'
  189.     if profile.has_key(field) and profile[field]:
  190.         str = profile[field]
  191.     return str
  192.  
  193. def get_description(profile):
  194.     '''Retrieve the description from the profile'''
  195.     str = ""
  196.     field = 'description'
  197.     if profile.has_key(field) and profile[field]:
  198.         str = profile[field]
  199.     return str
  200.  
  201. def get_ports(profile):
  202.     '''Retrieve a list of ports from a profile'''
  203.     ports = []
  204.     field = 'ports'
  205.     if profile.has_key(field) and profile[field]:
  206.         ports = profile[field].split('|')
  207.  
  208.     return ports
  209.  
  210.